#pragma once

#include "utils/ring_buffer.h"
#include "utils/memory_pool.h"
#include "utils/simd_math.h"
#include "utils/simd_math_ext.h"
#include <string>
#include <unordered_map>
#include <memory>
#include <vector>
#include <mutex>
#include <algorithm>
#include <tuple>

namespace hft {

/**
 * @brief 高度优化的价差历史管理器
 * 
 * 这个类专门用于统计套利策略，管理两个交易品种之间的价差历史。
 * 它使用RingBuffer、内存池和SIMD指令来优化价差历史数据的存储和计算。
 */
class OptimizedSpreadHistory {
public:
    /**
     * @brief 构造函数
     * @param symbol1 第一个交易品种
     * @param symbol2 第二个交易品种
     * @param capacity 历史数据容量
     */
    OptimizedSpreadHistory(const std::string& symbol1, const std::string& symbol2, size_t capacity = 1000)
        : symbol1_(symbol1)
        , symbol2_(symbol2)
        , spreads_(capacity)
        , sum_(0.0)
        , sum_sq_(0.0)
        , count_(0)
        , capacity_(capacity) {
    }
    
    /**
     * @brief 添加价差数据
     * @param price1 第一个交易品种的价格
     * @param price2 第二个交易品种的价格
     * @return 计算的价差
     */
    double addPrices(double price1, double price2) {
        std::lock_guard<std::mutex> lock(mutex_);
        
        double spread = price1 - price2;
        
        if (count_ == capacity_) {
            // 缓冲区已满，移除最旧的价差
            double old_spread = spreads_[0];
            sum_ -= old_spread;
            sum_sq_ -= old_spread * old_spread;
        } else {
            // 缓冲区未满，增加计数
            ++count_;
        }
        
        // 添加新价差
        spreads_.push_back(spread);
        sum_ += spread;
        sum_sq_ += spread * spread;
        
        return spread;
    }
    
    /**
     * @brief 添加价差数据
     * @param spread 价差
     */
    void addSpread(double spread) {
        std::lock_guard<std::mutex> lock(mutex_);
        
        if (count_ == capacity_) {
            // 缓冲区已满，移除最旧的价差
            double old_spread = spreads_[0];
            sum_ -= old_spread;
            sum_sq_ -= old_spread * old_spread;
        } else {
            // 缓冲区未满，增加计数
            ++count_;
        }
        
        // 添加新价差
        spreads_.push_back(spread);
        sum_ += spread;
        sum_sq_ += spread * spread;
    }
    
    /**
     * @brief 获取最新价差
     * @return 最新价差
     */
    double getLatestSpread() const {
        std::lock_guard<std::mutex> lock(mutex_);
        if (count_ == 0) return 0.0;
        return spreads_[count_ - 1];
    }
    
    /**
     * @brief 获取指定位置的价差
     * @param index 索引（0表示最旧的价差）
     * @return 价差
     */
    double getSpread(size_t index) const {
        std::lock_guard<std::mutex> lock(mutex_);
        if (index >= count_) return 0.0;
        return spreads_[index];
    }
    
    /**
     * @brief 获取价差数组
     * @return 价差数组
     */
    std::vector<double> getSpreads() const {
        std::lock_guard<std::mutex> lock(mutex_);
        std::vector<double> result(count_);
        for (size_t i = 0; i < count_; ++i) {
            result[i] = spreads_[i];
        }
        return result;
    }
    
    /**
     * @brief 获取价差数量
     * @return 价差数量
     */
    size_t getCount() const {
        std::lock_guard<std::mutex> lock(mutex_);
        return count_;
    }
    
    /**
     * @brief 获取容量
     * @return 容量
     */
    size_t getCapacity() const {
        return capacity_;
    }
    
    /**
     * @brief 清空价差历史
     */
    void clear() {
        std::lock_guard<std::mutex> lock(mutex_);
        spreads_.clear();
        sum_ = 0.0;
        sum_sq_ = 0.0;
        count_ = 0;
    }
    
    /**
     * @brief 计算价差均值
     * @param period 周期（0表示所有数据）
     * @return 均值
     */
    double calculateMean(size_t period = 0) const {
        std::lock_guard<std::mutex> lock(mutex_);
        
        if (count_ == 0) return 0.0;
        
        if (period == 0 || period >= count_) {
            // 使用预计算的总和
            return sum_ / count_;
        } else {
            // 计算指定周期的均值
            const double* data = spreads_.data() + (count_ - period);
            return utils::simd::mean(data, period);
        }
    }
    
    /**
     * @brief 计算价差标准差
     * @param period 周期（0表示所有数据）
     * @return 标准差
     */
    double calculateStdDev(size_t period = 0) const {
        std::lock_guard<std::mutex> lock(mutex_);
        
        if (count_ <= 1) return 0.0;
        
        if (period == 0 || period >= count_) {
            // 使用预计算的总和和平方和
            double mean = sum_ / count_;
            double variance = (sum_sq_ - 2 * mean * sum_ + count_ * mean * mean) / (count_ - 1);
            return std::sqrt(std::max(0.0, variance));
        } else {
            // 计算指定周期的标准差
            const double* data = spreads_.data() + (count_ - period);
            return utils::simd::stdDev(data, period);
        }
    }
    
    /**
     * @brief 计算价差Z-Score（标准分数）
     * @param period 周期（0表示所有数据）
     * @return Z-Score
     */
    double calculateZScore(size_t period = 0) const {
        std::lock_guard<std::mutex> lock(mutex_);
        
        if (count_ <= 1) return 0.0;
        
        double latest = spreads_[count_ - 1];
        double mean = calculateMean(period);
        double std_dev = calculateStdDev(period);
        
        if (std_dev < 1e-10) return 0.0;
        return (latest - mean) / std_dev;
    }
    
    /**
     * @brief 计算半衰指数移动平均（Half-Life Exponential Moving Average）
     * @param half_life 半衰期
     * @return 半衰指数移动平均
     */
    double calculateHalfLifeEMA(double half_life) const {
        std::lock_guard<std::mutex> lock(mutex_);
        
        if (count_ == 0 || half_life <= 0.0) return 0.0;
        
        // 计算衰减因子
        double decay_factor = std::exp(std::log(0.5) / half_life);
        
        double sum = 0.0;
        double weight_sum = 0.0;
        double weight = 1.0;
        
        for (int i = count_ - 1; i >= 0; --i) {
            sum += spreads_[i] * weight;
            weight_sum += weight;
            weight *= decay_factor;
        }
        
        return sum / weight_sum;
    }
    
    /**
     * @brief 计算协整检验的Dickey-Fuller统计量
     * @param lags 滞后阶数
     * @return Dickey-Fuller统计量
     */
    double calculateDickeyFullerStat(size_t lags = 1) const {
        std::lock_guard<std::mutex> lock(mutex_);
        
        if (count_ <= lags + 2) return 0.0;
        
        // 计算价差的一阶差分
        std::vector<double> diff(count_ - 1);
        for (size_t i = 0; i < count_ - 1; ++i) {
            diff[i] = spreads_[i + 1] - spreads_[i];
        }
        
        // 准备回归变量
        std::vector<double> y(diff.size() - lags);
        std::vector<double> x(diff.size() - lags);
        
        for (size_t i = lags; i < diff.size(); ++i) {
            y[i - lags] = diff[i];
            x[i - lags] = spreads_[i];
        }
        
        // 计算均值
        double mean_y = 0.0;
        double mean_x = 0.0;
        
        for (size_t i = 0; i < y.size(); ++i) {
            mean_y += y[i];
            mean_x += x[i];
        }
        
        mean_y /= y.size();
        mean_x /= x.size();
        
        // 计算回归系数
        double numerator = 0.0;
        double denominator = 0.0;
        
        for (size_t i = 0; i < y.size(); ++i) {
            double x_centered = x[i] - mean_x;
            double y_centered = y[i] - mean_y;
            
            numerator += x_centered * y_centered;
            denominator += x_centered * x_centered;
        }
        
        if (std::abs(denominator) < 1e-10) return 0.0;
        
        double beta = numerator / denominator;
        
        // 计算残差
        std::vector<double> residuals(y.size());
        for (size_t i = 0; i < y.size(); ++i) {
            residuals[i] = y[i] - beta * x[i];
        }
        
        // 计算残差标准差
        double residual_sum = 0.0;
        for (const auto& r : residuals) {
            residual_sum += r * r;
        }
        
        double residual_std = std::sqrt(residual_sum / (residuals.size() - 1));
        
        // 计算标准误差
        double std_error = residual_std / std::sqrt(denominator);
        
        // 计算t统计量
        return beta / std_error;
    }
    
    /**
     * @brief 计算Hurst指数
     * @return Hurst指数
     */
    double calculateHurstExponent() const {
        std::lock_guard<std::mutex> lock(mutex_);
        
        if (count_ < 100) return 0.5; // 默认值
        
        // 计算不同时间尺度的R/S值
        std::vector<double> log_rs;
        std::vector<double> log_n;
        
        for (size_t n = 10; n <= count_ / 2; n *= 2) {
            double rs_avg = 0.0;
            size_t num_segments = count_ / n;
            
            for (size_t i = 0; i < num_segments; ++i) {
                // 计算每个分段的R/S值
                std::vector<double> segment(n);
                for (size_t j = 0; j < n; ++j) {
                    segment[j] = spreads_[i * n + j];
                }
                
                // 计算均值
                double mean = 0.0;
                for (const auto& val : segment) {
                    mean += val;
                }
                mean /= n;
                
                // 计算累积离差
                std::vector<double> cum_dev(n);
                for (size_t j = 0; j < n; ++j) {
                    cum_dev[j] = segment[j] - mean;
                    if (j > 0) {
                        cum_dev[j] += cum_dev[j - 1];
                    }
                }
                
                // 计算范围R
                double r = *std::max_element(cum_dev.begin(), cum_dev.end()) - 
                          *std::min_element(cum_dev.begin(), cum_dev.end());
                
                // 计算标准差S
                double s = utils::simd::stdDev(segment.data(), n);
                
                if (s > 1e-10) {
                    rs_avg += r / s;
                }
            }
            
            if (num_segments > 0) {
                rs_avg /= num_segments;
                log_rs.push_back(std::log(rs_avg));
                log_n.push_back(std::log(static_cast<double>(n)));
            }
        }
        
        // 线性回归计算Hurst指数
        if (log_rs.size() < 2) return 0.5;
        
        double mean_log_rs = 0.0;
        double mean_log_n = 0.0;
        
        for (size_t i = 0; i < log_rs.size(); ++i) {
            mean_log_rs += log_rs[i];
            mean_log_n += log_n[i];
        }
        
        mean_log_rs /= log_rs.size();
        mean_log_n /= log_n.size();
        
        double numerator = 0.0;
        double denominator = 0.0;
        
        for (size_t i = 0; i < log_rs.size(); ++i) {
            double log_n_centered = log_n[i] - mean_log_n;
            double log_rs_centered = log_rs[i] - mean_log_rs;
            
            numerator += log_n_centered * log_rs_centered;
            denominator += log_n_centered * log_n_centered;
        }
        
        if (std::abs(denominator) < 1e-10) return 0.5;
        
        return numerator / denominator;
    }
    
    /**
     * @brief 计算半方差（半标准差）
     * @param period 周期（0表示所有数据）
     * @return 半方差
     */
    double calculateSemiVariance(size_t period = 0) const {
        std::lock_guard<std::mutex> lock(mutex_);
        
        if (count_ <= 1) return 0.0;
        
        double mean = calculateMean(period);
        double sum_sq_neg = 0.0;
        size_t count_neg = 0;
        
        if (period == 0 || period >= count_) {
            // 使用所有数据
            for (size_t i = 0; i < count_; ++i) {
                if (spreads_[i] < mean) {
                    double diff = spreads_[i] - mean;
                    sum_sq_neg += diff * diff;
                    ++count_neg;
                }
            }
        } else {
            // 使用指定周期的数据
            size_t start = count_ - period;
            for (size_t i = start; i < count_; ++i) {
                if (spreads_[i] < mean) {
                    double diff = spreads_[i] - mean;
                    sum_sq_neg += diff * diff;
                    ++count_neg;
                }
            }
        }
        
        if (count_neg <= 1) return 0.0;
        return std::sqrt(sum_sq_neg / count_neg);
    }
    
    /**
     * @brief 获取交易品种
     * @return {symbol1, symbol2}
     */
    std::pair<std::string, std::string> getSymbols() const {
        return {symbol1_, symbol2_};
    }
    
private:
    std::string symbol1_;                // 第一个交易品种
    std::string symbol2_;                // 第二个交易品种
    utils::RingBuffer<double> spreads_;  // 价差历史
    double sum_;                         // 价差之和
    double sum_sq_;                      // 价差平方和
    size_t count_;                       // 当前价差数量
    size_t capacity_;                    // 容量
    mutable std::mutex mutex_;           // 互斥锁
};

/**
 * @brief 多对价差历史管理器
 * 
 * 这个类管理多对交易品种的价差历史，使用哈希表快速查找特定对的价差历史。
 */
class OptimizedMultiSpreadHistory {
public:
    /**
     * @brief 构造函数
     * @param capacity 每对交易品种的历史数据容量
     */
    explicit OptimizedMultiSpreadHistory(size_t capacity = 1000)
        : capacity_(capacity) {
    }
    
    /**
     * @brief 添加价差数据
     * @param symbol1 第一个交易品种
     * @param symbol2 第二个交易品种
     * @param price1 第一个交易品种的价格
     * @param price2 第二个交易品种的价格
     * @return 计算的价差
     */
    double addPrices(const std::string& symbol1, const std::string& symbol2, double price1, double price2) {
        std::lock_guard<std::mutex> lock(mutex_);
        
        std::string key = getKey(symbol1, symbol2);
        
        auto it = spread_histories_.find(key);
        if (it == spread_histories_.end()) {
            // 创建新的价差历史
            auto history = std::make_shared<OptimizedSpreadHistory>(symbol1, symbol2, capacity_);
            double spread = history->addPrices(price1, price2);
            spread_histories_[key] = history;
            return spread;
        } else {
            // 添加到现有价差历史
            return it->second->addPrices(price1, price2);
        }
    }
    
    /**
     * @brief 获取指定对的价差历史
     * @param symbol1 第一个交易品种
     * @param symbol2 第二个交易品种
     * @return 价差历史指针
     */
    std::shared_ptr<OptimizedSpreadHistory> getSpreadHistory(const std::string& symbol1, const std::string& symbol2) const {
        std::lock_guard<std::mutex> lock(mutex_);
        
        std::string key = getKey(symbol1, symbol2);
        
        auto it = spread_histories_.find(key);
        if (it == spread_histories_.end()) {
            return nullptr;
        }
        return it->second;
    }
    
    /**
     * @brief 获取所有交易对
     * @return 交易对列表
     */
    std::vector<std::pair<std::string, std::string>> getPairs() const {
        std::lock_guard<std::mutex> lock(mutex_);
        
        std::vector<std::pair<std::string, std::string>> pairs;
        pairs.reserve(spread_histories_.size());
        
        for (const auto& pair : spread_histories_) {
            pairs.push_back(pair.second->getSymbols());
        }
        
        return pairs;
    }
    
    /**
     * @brief 清空指定对的价差历史
     * @param symbol1 第一个交易品种
     * @param symbol2 第二个交易品种
     */
    void clear(const std::string& symbol1, const std::string& symbol2) {
        std::lock_guard<std::mutex> lock(mutex_);
        
        std::string key = getKey(symbol1, symbol2);
        
        auto it = spread_histories_.find(key);
        if (it != spread_histories_.end()) {
            it->second->clear();
        }
    }
    
    /**
     * @brief 清空所有价差历史
     */
    void clearAll() {
        std::lock_guard<std::mutex> lock(mutex_);
        
        for (auto& pair : spread_histories_) {
            pair.second->clear();
        }
    }
    
private:
    /**
     * @brief 生成交易对的唯一键
     * @param symbol1 第一个交易品种
     * @param symbol2 第二个交易品种
     * @return 唯一键
     */
    static std::string getKey(const std::string& symbol1, const std::string& symbol2) {
        // 按字典序排序，确保 (A,B) 和 (B,A) 生成相同的键
        if (symbol1 < symbol2) {
            return symbol1 + ":" + symbol2;
        } else {
            return symbol2 + ":" + symbol1;
        }
    }
    
    std::unordered_map<std::string, std::shared_ptr<OptimizedSpreadHistory>> spread_histories_;
    size_t capacity_;
    mutable std::mutex mutex_;
};

} // namespace hft